/**
 * 2017年3月10日
 */
package cn.edu.bjtu.alex.hotswap;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Alex
 *
 */
public class TextCateClassLoader extends ClassLoader{
	private class Pair{
		public Class<?> clz;
		public long lastModified;
		public Pair(Class<?> clz ,long l){
			this.clz = clz;
			this.lastModified = l;
		}
	}
	final String classFileDir; 
	private final Map<String,Pair> cache = new HashMap<>(50);
	public TextCateClassLoader(){
		this.classFileDir = TextCateClassLoader.class.getResource("/").getFile();
	}
	private File getAbsPath(String name){
		String relPath = name.replace(".", System.getProperty("file.separator"))+".class";
		return new File(this.classFileDir,relPath);
	}
	private Class<?> myload(String name,File f){
		FileInputStream fis = null;
		ByteArrayOutputStream baos = null;
		try{
			fis = new FileInputStream(f);
			//1M的空间,超过1M的CLASS文件不多
			baos = new ByteArrayOutputStream(1024*1024);
			int c = -1;
			while(-1!=(c=fis.read())){
				baos.write(c);
			}
			Class<?> defined = defineClass(null,baos.toByteArray(),0,baos.size());
			System.out.println("read file and load file");
			cache.put(name, new Pair(defined,f.lastModified()));
			return defined;
		}catch (Exception e){
			throw new RuntimeException(e);
		}finally{
			try{
				fis.close();
				baos.close();
			}catch(Exception e){
				//ignroesa
			}
		}
	}
	
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		//name 是cn.bjtu.alex.hotswap.A这样的名字
		if(!name.startsWith("cn.edu.bjtu")) throw new RuntimeException("only used to load cn.edu.bjtu.*");
		File f = getAbsPath(name);
		if(cache.containsKey(name)){
			Pair p = cache.get(name);
			if(p.lastModified == f.lastModified()){
				return p.clz;
			}
		}
		return myload(name,f);
	
	}
}
